package util

import (
	"fmt"
	"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common"
	"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/errors"
	"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/profile"
	"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/regions"
	ocr "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ocr/v20181119"
	"goocr/config"
	"regexp"
	"strconv"
	"strings"
	"time"
)

const endPoint = "ocr.tencentcloudapi.com"

type OcrInfo struct {
	X    int64
	Y    int64
	Data string
}

func OcrImage(imgB64 string) ([]*OcrInfo, error) {
	var rsp []*OcrInfo
	credential := common.NewCredential(config.Conf.SecretId, config.Conf.SecretKey)
	cpf := profile.NewClientProfile()
	cpf.HttpProfile.Endpoint = endPoint
	client, err := ocr.NewClient(credential, regions.Guangzhou, cpf)
	if err != nil {
		return nil, err
	}
	// 构造请求参数
	request := ocr.NewGeneralBasicOCRRequest()
	request.ImageBase64 = common.StringPtr(imgB64)

	// 执行请求
	response, err := client.GeneralBasicOCR(request)
	if _, ok := err.(*errors.TencentCloudSDKError); ok {
		return nil, err
	}
	ts := response.Response.TextDetections
	for _, t := range ts {
		rsp = append(rsp, &OcrInfo{
			*t.ItemPolygon.X,
			*t.ItemPolygon.Y,
			*t.DetectedText,
		})
	}
	return rsp, nil
}

type Player struct {
	Id       int64
	Nickname string
	Score    int64
}
type RoomData struct {
	Code     int64
	RomeTime *time.Time
	Players  []Player
}

func GerOcrRsp(ocrs []*OcrInfo) (*RoomData, error) {
	var rooms RoomData
	//获取房号
	roomCood := getRoomCode(ocrs)
	if roomCood == "" {
		return nil, fmt.Errorf("picture not have room info")
	}
	//获取用户id列表
	userIds := getUserIds(ocrs)
	if len(userIds) < 2 {
		return nil, fmt.Errorf("too few players")
	}
	//获取用户Y坐标map
	userXMap := getUserXMap(userIds, ocrs)
	//昵称
	userNameMap := getUserNameMap(userXMap, ocrs)
	//分数
	userScoreMap := getUserScoreMap(userXMap, ocrs)
	//日期
	roomData := getRoomData(ocrs)

	var players []Player
	for _, id := range userIds {
		players = append(players, Player{
			Id:       id,
			Nickname: userNameMap[fmt.Sprint(id)],
			Score:    userScoreMap[fmt.Sprint(id)],
		})
	}
	roomCood = strings.TrimSpace(roomCood)
	rooms.Code, _ = stringToInt64(roomCood)
	rooms.RomeTime = roomData
	rooms.Players = players
	return &rooms, nil
}
func isContinue(data string) bool {
	//关键词返回
	if HaveInvalidDatas(data) {
		return true
	}
	//为空返回
	dataValues := []string{" ", "VP", "mvp"}
	for _, value := range dataValues {
		v := strings.ToLower(data)
		if v == value {
			return true
		}
	}
	//日期返回
	if isDateValid(data) {
		return true
	}

	return false
}
func getRoomData(ocrs []*OcrInfo) *time.Time {
	// 定义时间格式
	const layout = "2006-01-02 15:04:05"
	for _, info := range ocrs {
		data, err := parseDateTime(info.Data)
		if err != nil {
			continue
		}
		//日期返回
		if isDateValid(data) {
			ts := strings.TrimSpace(data)
			// 使用 time.Parse 转换字符串为时间对象
			t, err := time.Parse(layout, ts)
			if err != nil {
				continue
			}
			return &t
		}
	}
	now := time.Now().Add(-12 * time.Hour)
	return &now
}
func getUserNameMap(userXMap map[string]int64, ocrs []*OcrInfo) map[string]string {
	userNameMap := make(map[string]string)
	roomFront := true
	for _, od := range ocrs {
		data := od.Data
		if isContinue(data) {
			continue
		}

		if strings.Contains(data, "房号") {
			roomFront = false
			continue
		}
		if roomFront {
			continue
		}
		x := od.X
		for uid, ux := range userXMap {
			minUx := ux - 80
			maxUx := ux + 80
			if x > minUx && x < maxUx {
				name := strings.ToLower(data)
				if name == uid {
					continue
				}
				userNameMap[uid] = name
			}
		}
		if userXMap[data] > 0 {
			break
		}
	}
	for uid, _ := range userXMap {
		if userNameMap[uid] != "" {
			continue
		}
		userNameMap[uid] = " "
	}
	return userNameMap
}
func getUserScoreMap(userXMap map[string]int64, ocrs []*OcrInfo) map[string]int64 {
	userScoreMap := make(map[string]int64)
	var maybeScore []*OcrInfo
	roomFront := true
	for _, od := range ocrs {
		data := od.Data
		if isContinue(data) {
			continue
		}
		if strings.Contains(data, "房号") {
			roomFront = false
			continue
		}
		if roomFront {
			continue
		}

		if userXMap[data] != 0 {
			maybeScore = make([]*OcrInfo, 0)
		}
		if userXMap[data] == 0 {
			maybeScore = append(maybeScore, od)
		}
	}
	for _, od := range maybeScore {
		data := od.Data
		x := od.X
		for uid, ux := range userXMap {
			minUx := ux - 80
			maxUx := ux + 80
			if x > minUx && x < maxUx {
				score, _ := stringToInt64(data)
				userScoreMap[uid] = score
			}
		}
	}
	for uid, _ := range userXMap {
		if userScoreMap[uid] != 0 {
			continue
		}
		userScoreMap[uid] = 0
	}
	return userScoreMap
}
func getUserXMap(userIds []int64, ocrs []*OcrInfo) map[string]int64 {
	userMap := make(map[string]int64)
	for _, id := range userIds {
		ids := fmt.Sprint(id)
		for _, ocr := range ocrs {
			data := ocr.Data
			data = strings.TrimSpace(data)
			if data == ids {
				userMap[ids] = ocr.X
			}
		}
	}
	return userMap
}
func getUserYMap(userIds []int64, ocrs []*OcrInfo) map[string]int64 {
	userMap := make(map[string]int64)
	for _, id := range userIds {
		ids := fmt.Sprint(id)
		for _, ocr := range ocrs {
			data := ocr.Data
			data = strings.TrimSpace(data)
			if data == ids {
				userMap[ids] = ocr.Y
			}
		}
	}
	return userMap
}
func getUserIds(ocrs []*OcrInfo) []int64 {
	userIds := make([]int64, 0)
	for _, ocr := range ocrs {
		data := strings.TrimSpace(ocr.Data)
		if isSixDigitNumber(data) {
			str := data
			id, _ := stringToInt64(str)
			userIds = append(userIds, id)
		}
	}
	return userIds
}
func getRoomCode(ocrs []*OcrInfo) string {
	for _, od := range ocrs {
		if strings.Contains(od.Data, "房号") {
			roomData := od.Data
			roomData = strings.ReplaceAll(roomData, "房号", "")
			roomData = strings.ReplaceAll(roomData, ":", "")
			roomData = strings.ReplaceAll(roomData, "：", "")
			roomData = strings.ReplaceAll(roomData, " ", "")
			roomData = strings.TrimSpace(roomData)
			return roomData
		}

	}
	return ""
}

// isDateValid 检查字符串是否为指定格式的日期
func isDateValid(dateStr string) bool {
	layout := "2006-01-02 15:04:05" // Go中使用的参考时间格式
	_, err := time.Parse(layout, dateStr)
	return err == nil // 如果没有错误，表示日期有效
}

// isSixDigitNumber 检查字符串是否为六位数字
func isSixDigitNumber(s string) bool {
	// 正则表达式匹配恰好六位数字
	pattern := `^\d{6}$`
	matched, _ := regexp.MatchString(pattern, s)
	return matched
}
func HaveInvalidDatas(data string) bool {
	InvalidDatas := []string{"返回大厅", "牌局战绩", "游戏结果", "微信分享", "房间续费", "总成情", "总成请", "总成绩", "MVP", "总成调"}
	for _, item := range InvalidDatas {
		if strings.Contains(data, item) {
			return true
		}
	}
	return false
}

// stringToInt64 将字符串转换为int64类型
func stringToInt64(s string) (int64, error) {
	// 尝试将字符串转换为int64，假定基数为10，且无大小限制
	result, err := strconv.ParseInt(s, 10, 64)
	if err != nil {
		return 0, err // 转换失败时返回错误
	}
	return result, nil // 转换成功时返回结果和nil错误
}

// parseDateTime 使用正则表达式解析日期时间字符串
func parseDateTime(input string) (string, error) {
	re := regexp.MustCompile(`(\d{4}-\d{2}-\d{2})[T\s]?(\d{2}:\d{2}:\d{2})`)
	matches := re.FindStringSubmatch(input)
	if len(matches) < 3 {
		return "", fmt.Errorf("invalid or unsupported datetime format")
	}
	return matches[1] + " " + matches[2], nil
}
